package application;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import Basics.Atom;
import Basics.MemDB;
import Basics.Program;
import Basics.Rule;
import Basics.Var;


public class Initializer 
{
	public static Program getProgram ()
	{
		/*
		RT(p_1 , t) :- numFollowers(p_1,n) , follows(p_2,p_1) , tweet(p_2 , t)
		RT(p_1 , t) :- follows(p_2,p_1) , follows(p_3,p_1) , tweet(p_2 , t) , tweet(p_3 , t)
		RT(p_1, t) :-  follows(p_2,p_1) , tweet(p_2, t)
		RT(p_1, t) :-  follows(p_2,p_1) , isInterestedIn(p_2, a), isInterestedIn(p_1, a)
		*/
		
		Var u_1 = new Var("user_1", "User");
		Var u_2 = new Var("user_2", "User");
		Var u_3 = new Var("user_3", "User");
		Var t = new Var("t", "Tweet");
		Var n = new Var("n", "Tweet");
		Var s = new Var("s", "Subject");
		
		Atom head_1 = new Atom("RT", u_1, t);
		Atom head_2 = new Atom("RT", u_1, t);
		Atom head_3 = new Atom("RT", u_1, t);
		Atom head_4 = new Atom("RT", u_1, t);
		Atom isInterestedIn_1 = new Atom("isInterestedIn", u_1, s);
		Atom isInterestedIn_2 = new Atom("isInterestedIn", u_2, s);
		Atom follows_1_1 = new Atom("follows", u_2, u_1);
		Atom follows_1_2 = new Atom("follows", u_2, u_1);
		Atom follows_1_3 = new Atom("follows", u_2, u_1);
		Atom follows_2 = new Atom("follows", u_3, u_1);
		Atom numFollowers = new Atom("numFollowers", u_1, n);
		Atom tweet_1_1 = new Atom("tweet", u_2, t);
		Atom tweet_1_2 = new Atom("tweet", u_2, t);
		Atom tweet_1_3 = new Atom("tweet", u_2, t);
		Atom tweet_2 = new Atom("tweet", u_3, t);
	
		Rule r1 = new Rule (head_1, 0.7, numFollowers, follows_1_1, tweet_1_1);
		//Rule r2 = new Rule (head_2, 0.4, follows_1_2, follows_2, tweet_1_2, tweet_2);
		Rule r3 = new Rule (head_3, 0.1, follows_1_2, tweet_1_3);
		Rule r4 = new Rule (head_4, 0.9, follows_1_3, isInterestedIn_1, isInterestedIn_2);
		
		return new Program(r1, r3, r4);//r2,
	}
	
	
	public static void updateDB ()
	{
		String [] names = makeData(50, 9999, 1000);
		String [] subjects = makeData(50, 99999, 10000);
		String [] tweets = makeData(50, 999999, 100000);
		String [] numFollowers = makeData(50, 9, 1);
		
		insertToDB("isInterestedIn", names, subjects);
		insertToDB("numFollowers", names, numFollowers);
		insertToDB("tweet", names, tweets);
		insertConnectionsToDB("isInterestedIn", connect(names, subjects));
		insertConnectionsToDB("follows", connect(names, names));
	}
	
	
	
	public static String [] makeData (int numOfNames, int upperLim, int lowerLim)
	{
		String [] retVal = new String [numOfNames];
		Random rand = new Random();
		for (int i = 0; i < numOfNames; i++) 
		{
			int randomNum = rand.nextInt((upperLim - lowerLim) + 1) + lowerLim;
			retVal [i] = Integer.toString(randomNum);	
		}

	    return retVal;
	}
	
	
	
	public static String [] makeDemoData (int numOfNames)
	{
		String [] retVal = new String [numOfNames];
		String [] subjects = {"football", "chess", "reading", "movies", "programming", "ski"};
		Random rand = new Random();
		for (int i = 0; i < numOfNames; i++) 
		{
			int randomNum = rand.nextInt(5 + 1);
			retVal [i] = subjects [randomNum];	
		}

	    return retVal;
	}
	
	
	
	private static Map<String, String> connect (String [] arr1, String [] arr2)
	{
		Map<String, String> connections = new HashMap<String, String>();
		List<String> toConnect = new ArrayList<String>();
		Random rand = new Random();
		for (String name : arr1)
		{
			double randomNum = rand.nextDouble();
			if (randomNum > 0.8) 
			{
				toConnect.add(name);
			}
		}
		
		for (String name : toConnect) 
		{
			for (String string : arr2) 
			{
				connections.put(name, string);
			}
		}

	    return connections;
	}
	
	
	
	private static void insertToDB (String relName, String [] arr1, String [] arr2)
	{
		for (int i = 0; i < arr1.length; i++) 
		{
			MemDB.getInstance().InsertToTable(relName, new ArrayList<String>(
				    Arrays.asList(arr1[i], arr2[i])));
		}
	}
	
	
	private static void insertConnectionsToDB (String relName, Map<String, String> connMap)
	{
		for (String key : connMap.keySet()) 
		{
			MemDB.getInstance().InsertToTable(relName, new ArrayList<String>(
				    Arrays.asList(key, connMap.get(key))));
		}
	}
}
